package org.tangdao.modules.file.web;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.tangdao.common.collect.MapUtils;
import org.tangdao.common.config.Global;
import org.tangdao.common.lang.StringUtils;
import org.tangdao.common.lang.TimeUtils;
import org.tangdao.common.mapper.JsonMapper;
import org.tangdao.common.suports.BaseController;
import org.tangdao.common.suports.DataEntity;
import org.tangdao.modules.file.model.domain.FileEntity;
import org.tangdao.modules.file.model.domain.FileUpload;
import org.tangdao.modules.file.model.vo.FileUploadParams;
import org.tangdao.modules.file.service.IFileEntityService;
import org.tangdao.modules.file.service.IFileUploadService;
import org.tangdao.modules.file.service.impl.FileUploadServiceExtend;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;

@Controller
@RequestMapping(value = { "${adminPath}/file" })
public class FileUploadController extends BaseController {

	@Autowired
	private IFileEntityService fileEntityService;

	@Autowired
	private IFileUploadService fileUploadService;

	@Autowired
	private FileUploadServiceExtend fileUploadServiceExtend;

	/**
	 * 文件列表
	 * 
	 * @param fileUpload
	 * @return
	 */
	@RequestMapping(value = { "list" })
	public @ResponseBody String fileList(FileUpload fileUpload) {
		List<FileUpload> result;
		if (StringUtils.isNotBlank(fileUpload.getBizKey()) && StringUtils.isNotBlank(fileUpload.getBizType())
				&& (result = this.fileUploadService.findList(fileUpload)) != null && result.size() > 0) {
			return JsonMapper.toJson(result);
		}
		return this.renderResult(Global.FALSE, "No files.");
	}

	/**
	 * 文件预览
	 * 
	 * @param fileUploadId
	 * @param preview
	 * @param request
	 * @param response
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping(value = { "/download/{fileUploadId}" }, method = { RequestMethod.GET })
	public String download(@PathVariable(value = "fileUploadId") String fileUploadId, String preview,
			HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		FileUpload fileUpload = this.fileUploadService.get(fileUploadId);
		if (fileUpload != null && fileUpload.getFileEntity() != null
				&& fileUpload.getFileEntity().getFileMd5() != null) {
			if (StringUtils.isNotBlank(preview)) {
				String fileUrl = fileUpload.getFileUrl();
				String fileUrlExt = StringUtils.contains(fileUrl, "?") ? "&" : "?";
				return "redirect:" + fileUrl + fileUrlExt + "preview=" + preview;
			}
			String result = this.fileUploadServiceExtend.downFile(fileUpload, request, response);
			if (!"404".equals(result)) {
				if (StringUtils.isNotBlank(result)) {
					return "redirect:" + result;
				}
				return null;
			}
		}
		request.setAttribute("responseStatus", 200);
		request.setAttribute("message", "文件已丢失或不存在！");
		request.getRequestDispatcher("/error/404").forward(request, response);
		return null;
	}

	/**
	 * 双重文件
	 * @param params
	 * @param status
	 * @param request
	 * @return
	 */
	@RequestMapping(value = { "upload" })
	public @ResponseBody String upload(FileUploadParams params, String status, HttpServletRequest request) {
		long startTime = System.currentTimeMillis();
		Map<String, Object> map = MapUtils.newHashMap();
		map.put("code", "server");
		if (StringUtils.isBlank(params.getFileMd5()) || StringUtils.isBlank(params.getFileName())) {
			return this.renderResult(Global.FALSE, "上传文件不能为空", map);
		}
		FileEntity fileEntity = this.fileEntityService.getByMd5(params.getFileMd5());
		fileEntity.setFileUploadParams(params);
		params.initialize();
		boolean isUsed = false;
		if (!DataEntity.STATUS_NORMAL.equals(fileEntity.getStatus())) {
			isUsed = true;
		}
		if (isUsed) {
			MultipartHttpServletRequest mhsr;
			Iterator<String> fileName;
			MultipartFile multipartFile = null;
			if (request instanceof MultipartHttpServletRequest
					&& ((fileName = (mhsr = (MultipartHttpServletRequest) request).getFileNames()).hasNext())) {
				multipartFile = mhsr.getFile(fileName.next());
			}
			if (multipartFile == null || multipartFile.isEmpty() || multipartFile.getOriginalFilename() == null) {
				return this.renderResult(Global.FALSE, "上传文件是空的", map);
			}

			String allowSuffixes = params.getAllowSuffixes();
			if (!StringUtils.contains(allowSuffixes, ("." + params.getFileExtension() + ","))) {
				String uploadType = params.getUploadType();
				map.put("code", "not_allow_type");
				if ("image".equals(uploadType)) {
					return this.renderResult(Global.FALSE, "只能上传指定格式的图片", map);
				}
				if ("media".equals(uploadType)) {
					return this.renderResult(Global.FALSE, "只能上传指定格式的视频", map);
				}
				if ("file".equals(uploadType)) {
					return this.renderResult(Global.FALSE, "只能上传指定格式的文件", map);
				}
				return this.renderResult(Global.FALSE, "上传文件格式错误", map);
			}
			long size = multipartFile.getSize();
			if (size > params.getMaxFileSize().longValue()) {
				map.put("code", "exceed_size");
				return this.renderResult(Global.FALSE, "不能超过指定大小", map);
			}
			boolean isNewRecord = false;
			if (StringUtils.isBlank(fileEntity.getFileId())) {
				fileEntity.setFileId(IdWorker.getIdStr());
				fileEntity.setFileMd5(params.getFileMd5());
				fileEntity.setFilePath(params.getRelativePath());
				fileEntity.setFileContentType(multipartFile.getContentType());
				fileEntity.setFileExtension(params.getFileExtension());
				fileEntity.setFileSize(size);
				isNewRecord = true;
			}
			File file;
			if (!(file = new File(fileEntity.getFileRealPath())).getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			try {
				multipartFile.transferTo(file);
			} catch (IOException e) {
				e.printStackTrace();
			}
			String allowContentTypes = Global.getConfig("file.allowContentTypes");
			if (StringUtils.isNotBlank(allowContentTypes)
					&& !StringUtils.inString(multipartFile.getContentType(), allowContentTypes.split(","))) {
				map.put("code", "not_allow_type");
				file.delete();
				return this.renderResult(Global.FALSE, "文件内容格式不允许", map);
			}
			fileUploadService.compressImage(params, file);
			fileUploadServiceExtend.uploadFile(fileEntity);
			if (isNewRecord) {
				this.fileEntityService.insert(fileEntity);
			}
		}
		FileUpload fileUpload = new FileUpload(fileEntity);
		fileUpload.setFileName(params.getFileName());
		fileUpload.setFileType(params.getUploadType());
		fileUploadServiceExtend.saveUploadFile(fileUpload);
		fileUploadService.saveOrUpdate(fileUpload);
		long endTime = System.currentTimeMillis();
		String ms = TimeUtils.formatDateAgo(endTime - startTime);
		map.put("fileUpload", fileUpload);
		if (!isUsed) {
			return this.renderResult(Global.TRUE, String.format("秒传成功，用时 %s", ms), map);
		}
		return this.renderResult(Global.TRUE, String.format("上传成功，用时 %s", ms), map);
	}
}
